#ifndef _DAT_OBJECT_H_
#define _DAT_OBJECT_H_

#include "opencv2/opencv.hpp"

//DAT means Detected And Tracked

#include <vector>
#include <string>
using namespace std;

//these values are, for now, defined arbitrarily
#define	ALIVE 4
#define DEATH 4

#define USE_GENERAL_CONFIDANCE
#define ALIVE_CONFIDANCE 0.9


//#define	ALIVE 0
//#define DEATH 0

enum DoT	//Detected or tracked (usefull in Tracker and for the DATReader, etc.)
{
	DeadAllAlong = -1,
	Nothing = 0,
	Detected = 1,
	Tracked = 2,
	DetectedAndTracked = 3,
	GroundTruth = 4
};

enum LivingState //0 = Uncertain, 1 = Alive, 2 = Dead (was alive, now's dead), 3 = Undead (never really alive)
{
	Merged = -1,
	Uncertain = 0,
	Living = 1,
	Dead = 2,
	Undead = 3
};

struct DATObjectHistory
{
	DATObjectHistory(unsigned int inSize=0) : mPositions(inSize), mWasDetected(inSize), mObjectType(inSize), mConfidences(inSize), mFrameMapping(inSize)
	{}

	int findFrame(int inFrame, bool inMustBeDetected = false)
	{
		for(unsigned int i=0;mFrameMapping.size();i++)
			if(mFrameMapping[i] == inFrame && (mWasDetected[i] || !inMustBeDetected))
				return i;
		return -1;
	}
	void push_back(cv::Rect inPosition, bool inWasDetected, std::string inObjectType, double inConfidence, int inFramePos)
	{
		mPositions.push_back(inPosition);
		mWasDetected.push_back(inWasDetected);
		mObjectType.push_back(inObjectType);
		mConfidences.push_back(inConfidence);
		mFrameMapping.push_back(inFramePos);
	}
	void resize(int inSize)
	{
		mPositions.resize(inSize);
		mWasDetected.resize(inSize);
		mObjectType.resize(inSize);
		mConfidences.resize(inSize);
		mFrameMapping.resize(inSize);
	}

	vector<cv::Rect>		mPositions;

	vector<bool>			mWasDetected;

	vector<string>			mObjectType; //only when "WasDetected" is true;

	vector<double>			mConfidences;

	vector<unsigned int>	mFrameMapping;//contains the frame associated with the vector indexes
};

struct DATObject
{
	DATObject()
	{
		mLastWasDetected = true;		//whenever i create one of those, its because of a detection...
		mLastPosition.x = mLastPosition.y = mLastPosition.width = mLastPosition.height = -1;
		mLastObjectType = ""; //should be filled really quickly
		mLastConfidence = 0.0;
		mGeneralConfidence = 0.0;
		mFramePos = -1; //Should be filled really quickly

		mLifeCounter = 1; //It's the first detection
		mDeathCounter = DEATH;

		mLivingState = Uncertain;

		mID = -1;		//BAD
	};
	virtual ~DATObject()
	{

	};
	cv::Mat						mLastSeenObject;	//This struct totally own the image. Do not abuse.
	cv::Rect					mLastPosition;		
	bool						mLastWasDetected;	//Just to know if, in this frame, the object was detected or only tracked.
	string						mLastObjectType;	//Really useful for the management
	double						mLastConfidence;	//Of the last detection ! (not tracking... its not really important)
	double						mGeneralConfidence;	//Its the higher boundary of confidence (p = 1 - PI(1-p))

	//The counter only change when the object is detected (life) or when it's not tracked (death)
	double						mDeathCounter;		//it start with a high value "DEATH"... when it equals 0, the object is removed and he's delete
	int							mLifeCounter;		//it start at 1... when it equals "ALIVE" the object is considered "real"

	LivingState					mLivingState; 	//0 = Uncertain, 1 = Alive, 2 = Dead (was alive, now's dead), 3 = Undead (never really alive)

	DATObjectHistory			mHistory;		//Because I don't want/need to keep the image.
	int							mFramePos;

	int							mID;			//Only usefull when there's no tracker... put -1 inside
};

struct DATFrame	//in case we need derived form with exceeding data
{
	DATFrame() : mROI(0,0,0,0)
	{
		mFramePos = -1;
	};
	virtual ~DATFrame()
	{

	};

	cv::Mat			mActualFrame;	//This struct totally own the Image. Do not abuse.
	int				mFramePos;
	cv::Rect		mROI;
};

#endif
